#ifndef __COMM_IMPL_H
#define __COMM_IMPL_H

#include "../utils/byte_buf.h"
#include "../utils/exception.h"
#include "./proto.h"
#include <asio.hpp>
#include <thread>


namespace conn {

using namespace asio;

inline uint8_t sync(asio::serial_port &port) {
    bool flag = false;
    uint8_t value;
    for (;;) {
        port.read_some(asio::buffer(&value, 1));
        if (flag && (value == proto::HEAD1)) {
            break;
        }
        flag = value == proto::HEAD0;
    }
    port.read_some(asio::buffer(&value, 1));
    return value;
}

inline utils::ByteBuf recv(asio::serial_port &port) {
    uint8_t len = sync(port);
    if (len < 7) {
        throw utils::ProtoException("len invalid");
    }
    utils::ByteBuf buf(len - 3);
    asio::read(port, asio::buffer(buf.buf(), buf.len()));
    uint8_t s = 0;
    for (size_t i = 0; i < buf.len() - 2; i++) {
        s ^= buf[i];
    }
    if (buf[buf.len() - 2] != s) {
        throw utils::ProtoException("check sum invalid");
    }
    if (buf[buf.len() - 1] != proto::END) {
        throw utils::ProtoException("end invalid");
    }
    return buf;
}

} // namespace conn

#endif
